package main

import (
	"context"
	"fgo/advance/other/discovery/bilibili/example/conf"
	"fgo/advance/other/discovery/bilibili/example/grpc"
	"fgo/advance/other/discovery/bilibili/example/http"
	md "fgo/advance/other/discovery/bilibili/example/model"
	"fgo/advance/other/discovery/bilibili/example/pkg/ip"
	"flag"
	"github.com/bilibili/discovery/naming"
	resolver "github.com/bilibili/discovery/naming/grpc"
	"github.com/google/martian/log"
	"net"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
	"time"
)

const (
	appid = "goim.test"
)

// http://127.0.0.1:7171/discovery/fetchs?zone=sh001&env=dev&appid=goim.test&status=1
func main() {
	flag.Parse()
	if err := conf.Init(); err != nil {
		panic(err)
	}
	// register discovery
	dis := naming.New(conf.Conf.Discovery)
	resolver.Register(dis)
	// new server
	srv := http.NewServer(conf.Conf)

	// new grpc server
	grpc.New(conf.Conf.RPCServer, srv)
	cancel := register(dis, srv)

	// signal
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
	for {
		s := <-c
		switch s {
		case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
			cancel()
			srv.Close()
			time.Sleep(time.Second)
			return
		case syscall.SIGHUP:
		default:
			return
		}
	}
}
func register(dis *naming.Discovery, srv *http.Server) context.CancelFunc {
	env := conf.Conf.Env
	addr := ip.InternalIP()
	_, grpcPort, _ := net.SplitHostPort(conf.Conf.RPCServer.Addr)
	httpPort := conf.Conf.HttpConfig.Addr
	ins := &naming.Instance{
		Region:   env.Region,
		Zone:     env.Zone,
		Env:      env.DeployEnv,
		Hostname: env.Host,
		AppID:    appid,
		Addrs: []string{
			"grpc://" + addr + ":" + grpcPort,
			"http://" + addr + httpPort,
		},
		Metadata: map[string]string{
			md.MetaWeight: strconv.FormatInt(env.Weight, 10),
			md.MetaAddrs:  strings.Join(env.Addrs, ","),
		},
	}
	cancel, err := dis.Register(ins)
	if err != nil {
		panic(err)
	}
	// renew discovery metadata
	go func() {
		for {
			var (
				err error
			)
			if err = dis.Set(ins); err != nil {
				log.Errorf("dis.Set(%+v) error(%v)", ins, err)
				time.Sleep(time.Second)
				continue
			}
			time.Sleep(time.Second * 10)
		}
	}()
	return cancel
}
